10장 일정 관리 웹 애플리케이션 만들기
참조하려는 컴포넌트 창이 열러있지 않으면 import 자동으로 못해줌
→ jsconfig.json 만들어줘서 setting해줌
{
"compilerOptions": {
"target": "es2020"
}
}
해주면 창 닫혀있어도 자동 import 된다.
일정관리 웹 애플리케이션 만들기
TodoListItem이 각 할일 마다의 컴포넌트를 작성해주고 TodoList 가 TodoListItem 들을 이용해서 List를 출력한다.
TodoInsert 는 입력 수행
App에서 Todo와 함수들을 관리하고 props로 TodoList 에 넘겨준다.
const App = () => {
const [todos, setTodos] = useState([
{
id: 1,
text: "리액트의 기초 알아보기",
checked: true,
},
{
id: 2,
text: "컴포넌트 스타일링 해보기",
checked: true,
},
{
id: 3,
text: "일정 관리 앱 만들어 보기",
checked: false,
},
]);
const nextId = useRef(4);
const onInsert = useCallback(
(text) => {
setTodos([...todos, { id: nextId.current, text: text, cehcked: false }]);
nextId.current += 1;
},
[todos]
);
const onDelete = useCallback(
(id) => {
const newTodos = todos.filter((todo) => todo.id != id);
setTodos(newTodos);
},
[todos]
);
const onToggle = useCallback((id) => {
setTodos(
todos.map((todo) =>
id == todo.id ? { ...todo, checked: !todo.checked } : todo
)
);
});
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} onDelete={onDelete} onToggle={onToggle} />
</TodoTemplate>
);
};
export default App;
const TodoInsert = ({ onInsert }) => {
const [value, setValue] = useState("");
const onChange = useCallback((e) => {
setValue(e.target.value);
}, []);
const onSubmit = useCallback(
(e) => {
onInsert(value);
setValue("");
//submit 이벤트는 브라우저에서 새로고침을 발생시킴
// 이를 방지하기 위한 함수호출
e.preventDefault();
},
[onInsert, value]
);
return (
<form className="TodoInsert" onSubmit={onSubmit}>
<input
value={value}
placeholder="할 일을 입력하세요"
onChange={onChange}
/>
<button type="submit">
<MdAdd />
</button>
</form>
);
};
const TodoList = ({ todos, onDelete, onToggle }) => {
const todosList = todos.map((todo) => (
<TodoListItem
todo={todo}
key={todo.key}
onDelete={onDelete}
onToggle={onToggle}
/>
));
return <div className="TodoList">{todosList}</div>;
};
const TodoListItem = ({ todo, onDelete, onToggle }) => {
const { id, text, checked } = todo;
return (
<div className="TodoListItem">
<div className={cn("checkbox", { checked })} onClick={() => onToggle(id)}>
{/* `checkbox ${checked ? "checked" : ""}` */}
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text">{text}</div>
</div>
<div className="remove" onClick={() => onDelete(id)}>
<MdRemoveCircleOutline />
</div>
</div>
);
};